import { SpotlightDemos } from "@/lib/@docs/demos/src";
import { Layout } from "@/layout";
import { MDX_DATA } from "@/mdx";

export default Layout(MDX_DATA.Spotlight);

## Installation

<InstallScript packages="@mantine/spotlight" />

After installation import package styles at the root of your application:

```tsx
import "@mantine/spotlight/styles.css";
```

## Usage

`Spotlight` component can be used as a search or as a command center of your application.
It is used as a search on mantine.dev website, you can trigger it with `Ctrl + K` shortcut.
`Spotlight` is based on [Modal](/core/modal) component and supports most of its props.

<Demo data={SpotlightDemos.usage} />

## Actions

`@mantine/spotlight` package exports an object with actions that can be used to control the spotlight:

```tsx
import { spotlight } from "@mantine/spotlight";

spotlight.open(); // -> opens spotlight
spotlight.close(); // -> closes spotlight
spotlight.toggle(); // -> toggles spotlight opened state
```

These actions can be passed to event listeners or used anywhere in your application
(not limited to React components):

```tsx
import { Button } from "@mantine/core";
import { spotlight } from "@mantine/spotlight";

function Demo() {
  return <Button onClick={spotlight.open}>Open spotlight</Button>;
}
```

You can also import actions directly from the `@mantine/spotlight` package, if you prefer this syntax:

```tsx
import {
  closeSpotlight,
  openSpotlight,
  toggleSpotlight,
} from "@mantine/spotlight";

openSpotlight(); // same as spotlight.open()
closeSpotlight(); // same as spotlight.close()
toggleSpotlight(); // same as spotlight.toggle()
```

## Spotlight store

`spotlight` object documented above uses the default store, it works fine if you have only one spotlight
in your application. In case you need multiple spotlights, you need to create your own store for each of them:

```tsx
import { Button } from "@mantine/core";
import { createSpotlight, Spotlight } from "@mantine/spotlight";

// You can import `firstSpotlight` and `secondSpotlight` anywhere
// in your application and use `open`, `close` and `toggle` actions
// to control spotlight the same way as with default `spotlight` object
export const [firstStore, firstSpotlight] = createSpotlight();
export const [secondStore, secondSpotlight] = createSpotlight();

function Demo() {
  return (
    <>
      <Button onClick={firstSpotlight.open}>Open first spotlight</Button>
      <Button onClick={secondSpotlight.open}>Open second spotlight</Button>

      <Spotlight store={firstStore} actions={[]} />
      <Spotlight store={secondStore} actions={[]} />
    </>
  );
}
```

## Keyboard shortcuts

`Spotlight` uses [use-hotkeys](/hooks/use-hotkeys) hook to handle keyboard shortcuts.
By default, `Ctrl + K` and `Cmd + K` shortcuts are used to open spotlight, you can change them
with `shortcut` prop:

```tsx
import { Spotlight } from "@mantine/spotlight";

function SingleShortcut() {
  return <Spotlight shortcut="mod + J" actions={[]} />;
}

// Same as on mantine.dev
function MultipleShortcuts() {
  return <Spotlight shortcut={["mod + K", "mod + P", "/"]} actions={[]} />;
}

// Disable shortcut
function NoShortcut() {
  return <Spotlight shortcut={null} actions={[]} />;
}
```

## Limit prop

Use `limit` prop to limit the maximum number of actions that can be displayed at a time.
Usually, 5–7 actions is a good number. `limit` prop is crucial for performance in case
you have a lot of actions, it will prevent the spotlight from rendering all of them at once.

The example below renders 3000 actions, but only 7 of them are displayed at a time:

<Demo data={SpotlightDemos.limit} />

## Scrollable actions list

By default, `Spotlight` actions list is not scrollable. If you have a lot of actions that
you need to display at a time, set `scrollable` and `maxHeight` props. Note that there are
caveats with both approaches:

- When the `scrollable` prop is not set, actions list height is not limited and the spotlight
  body will grow to fit all actions. This can result in a very long spotlight body that will
  overflow the viewport. To prevent this, use `limit` prop to define the maximum number of actions
  that can be displayed at a time. Usually, 5–7 actions is a good number.
- When the `scrollable` prop is set, actions list height will always equal to the value of `maxHeight` prop
  (it will not shrink if there are not enough actions to fill the space). When there are more
  actions than can fit into the list, it will become scrollable. Scrolling logic is handled
  by [ScrollArea](/core/scroll-area) component.

In other words, if you want the actions list to shrink, do not set `scrollable` prop and use `limit`
prop. If you want the actions list to always have a fixed height, set `scrollable` and `maxHeight` props.

<Demo data={SpotlightDemos.scrollable} />

## Actions groups

`Spotlight` supports actions groups, you can use them to group actions by category:

<Demo data={SpotlightDemos.groups} />

## Compound components

If you need more control over spotlight rendering and logic, use compound components.
Available components:

- `Spotlight.Root` – root component, should be used as a wrapper for all other components, accepts all props to customize logic
- `Spotlight.Search` – search input
- `Spotlight.ActionsList` – list of actions, required to wrap all actions and actions groups
- `Spotlight.Action` – action button
- `Spotlight.ActionsGroup` - group of actions
- `Spotlight.Empty` – empty state (nothing found)

<Demo data={SpotlightDemos.compound} />

For example, with compound components pattern you can customize actions contents:

<Demo data={SpotlightDemos.customAction} />

## Fixed elements offset

`Spotlight` component uses [react-remove-scroll](https://github.com/theKashey/react-remove-scroll)
package to lock scroll. To properly size these `elements` add a `className` to them ([documentation](https://github.com/theKashey/react-remove-scroll#positionfixed-elements)):

```tsx
import { RemoveScroll } from "@mantine/core";

function Demo() {
  return (
    <>
      <div className={RemoveScroll.classNames.fullWidth}>width: 100%</div>
      <div className={RemoveScroll.classNames.zeroRight}>right: 0</div>
    </>
  );
}
```
